package com.coszero.utils.utils

import android.annotation.SuppressLint
import android.content.Context
import com.coszero.utils.R
import java.text.DateFormat
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale
import java.util.Random


/**
 * @author xmqian
 * @date 2018/5/29
 * @desc 获取系统时间，和格式化时间格式
 * @version 1
 */
object TimeUtils {
    private const val TAG: String = "TimeUtils"
    private val minute: Long = (60 * 1000 // 1分钟
            ).toLong()
    private val hour: Long = 60 * minute // 1小时
    private val day: Long = 24 * hour // 1天
    private val month: Long = 31 * day // 月
    private val year: Long = 12 * month // 年

    /*时间格式可根据需要进行更改*/
    /**
     * 日期格式：yyyy-MM-dd HH:mm:ss
     */
    const val DF_YYYY_MM_DD_HH_MM_SS: String = "yyyy-MM-dd HH:mm:ss"

    /**
     * 日期格式：yyyy-MM-dd HH:mm
     */
    const val DF_YYYY_MM_DD_HH_MM: String = "yyyy-MM-dd HH:mm"

    /**
     * 日期格式：yyyy-MM-dd
     */
    const val DF_YYYY_MM_DD: String = "yyyy-MM-dd"

    /**
     * 日期格式：HH:mm:ss
     */
    const val DF_HH_MM_SS: String = "HH:mm:ss"

    /**
     * 日期格式：HH:mm
     */
    const val DF_HH_MM: String = "HH:mm"

    /**
     * 日期格式：MM-dd HH:mm
     */
    const val DF_MM_DD_HH_MM: String = "MM-dd HH:mm"


    private var mCalendar: Calendar? = null
    private val format: SimpleDateFormat? = null

    // <editor-fold desc="返回当前时间" defaultstate="collapsed">
    val longTime: Long
        /**
         * 获取未经处理的时间格式
         *
         * @return 返回long类型的时间格式
         */
        get() = System.currentTimeMillis()

    val currentTime: String
        /**
         * 以默认格式获取当前的系统时间
         *
         * @return 返回月-日 时：分 格式的时间
         */
        get() = SimpleDateFormat(
            DF_MM_DD_HH_MM,
            Locale.CHINA
        )
            .format(Date())

    val currentDate: Date
        /**
         * 获取系统当前日期
         *
         * @return date
         */
        get() {
            return Date()
        }

    /**
     * 以你所需要的格式获取当前的系统时间
     *
     * @param rgx 传入你需要的时间格式
     * @return 返回你所需要格式的时间字符串
     */
    fun getCurrentTime(rgx: String?): String {
        return SimpleDateFormat(rgx, Locale.CHINA)
            .format(Date())
    }

    /**
     * 获取当前日期月
     *
     * @return 返回当前月份
     */
    fun getMonth(): Int {
        mCalendar = Calendar.getInstance()
        val mMonth: Int = mCalendar.get(Calendar.MONTH) + 1
        return mMonth
    }

    /**
     * 获取当前日期日
     *
     * @return 返回当前月的日
     */
    fun getDay(): Int {
        mCalendar = Calendar.getInstance()
        val mDay: Int = mCalendar.get(Calendar.DATE)
        return mDay
    }

    /**
     * 获取当前日期年
     *
     * @return 返回当前年
     */
    fun getYear(): Int {
        mCalendar = Calendar.getInstance()
        val year: Int = mCalendar.get(Calendar.YEAR)
        return year
    }

    //</editor-fold>
    // <editor-fold desc="时间操作" defaultstate="collapsed">
    // <editor-fold desc="判断" defaultstate="collapsed">
    /**
     * 验证日期是否比当前日期早
     *
     * @param startTime 当前系统时间
     * @param finishTime 需要比较的时间
     * @return 返回当前时间是否比finishTime早，早：true;晚false
     */
    fun compareData(startTime: String, finishTime: String): Boolean {
        val dateFormat: SimpleDateFormat = SimpleDateFormat(
            DF_YYYY_MM_DD_HH_MM_SS
        )
        var isLast: Boolean = false
        try {
            val startDate: Date? = dateFormat.parse(startTime)
            val finishDate: Date? = dateFormat.parse(finishTime)
            isLast = startDate!!.before(finishDate)
        } catch (e: ParseException) {
            println("比较失败，原因：" + e.message)
        }
        return isLast
    }

    /**
     * 判断两日期是否同一天
     *
     * @param str1 2019-01-30
     * @param str2 2019-01-29
     * @return
     */
    @SuppressLint("SimpleDateFormat")
    fun isToday(str1: String, str2: String): Boolean {
        var day1: Date? = null
        var day2: Date? = null
        day1 = parseDate(str1)
        day2 = parseDate(str2)
        val sdf: SimpleDateFormat = SimpleDateFormat(DF_YYYY_MM_DD)
        val ds1: String = sdf.format(day1)
        val ds2: String = sdf.format(day2)
        return ds1 == ds2
    }

    //</editor-fold>
    // <editor-fold desc="转化" defaultstate="collapsed">
    /**
     * 传入时间 算出星期几
     *
     * @param str 2014-1-3
     * @param days 1:2014-1-4 类推
     * @return 返回字符资源
     */
    @SuppressLint("SimpleDateFormat")
    fun getWeekName(str: String, days: Int): Int {
        var dateStr: Int = R.string.ut_monday
        try {
            val df: DateFormat = DateFormat.getDateInstance(DateFormat.LONG)
            val date: Date? = df.parse(str)
            val dateFormat: SimpleDateFormat = SimpleDateFormat(DF_YYYY_MM_DD)
            val c: Calendar = Calendar.getInstance()
            val d: Date? = dateFormat.parse(dateFormat.format(date))
            c.time = d
            c.add(Calendar.DAY_OF_MONTH, days)
            when (c.get(Calendar.DAY_OF_WEEK) - 1) {
                0 -> dateStr = R.string.ut_sunday
                1 -> dateStr = R.string.ut_monday
                2 -> dateStr = R.string.ut_thursday
                3 -> dateStr = R.string.ut_wednesday
                4 -> dateStr = R.string.ut_thursday
                5 -> dateStr = R.string.ut_friday
                6 -> dateStr = R.string.ut_saturday
                else -> {
                    dateStr = R.string.ut_monday
                    LogX.e(TAG, "### getWeekName：星期数值错误")
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return dateStr
    }

    /**
     * 将日期字符串转成日期
     *
     * @param strDate 字符串日期，需要"-"分割
     * @return java.util.date日期类型
     */
    @SuppressLint("SimpleDateFormat")
    fun parseDate(strDate: String): Date? {
        return parseDate(strDate, "-")
    }

    @SuppressLint("SimpleDateFormat")
    fun parseDate(strDate: String, split: String): Date? {
        if (!strDate.contains(split)) {
            LogX.e(TAG, "parseDate：" + "分隔符不正确")
            return null
        }
        val dateFormat: DateFormat =
            SimpleDateFormat("yyyy" + split + "MM" + split + "dd" + " HH:mm:ss")
        var returnDate: Date? = null
        try {
            returnDate = dateFormat.parse(strDate)
        } catch (e: ParseException) {
            LogX.e(TAG, "### parseDate:日期格式错误$strDate")
        }
        return returnDate
    }

    /**
     * 传入一个String转化为long
     *
     * @param param 传入的时间,格式为"-"
     * @return 返回一个long型
     * @throws ParseException
     */
    @SuppressLint("SimpleDateFormat")
    fun stringParserLong(param: String): Long {
        return parseDate(param)!!.time
    }

    /**
     * 将long类型日期以yyyy-MM-dd HH:mm:ss格式化
     *
     * @param dateL 传入以Date获取的long类型值
     * @return 返回已默认格式转化的时间字符串
     */
    @SuppressLint("SimpleDateFormat")
    fun formatDateTime(dateL: Long): String {
        return formatDateTime(dateL, DF_YYYY_MM_DD_HH_MM_SS)
    }

    /**
     * 格式化Date类型的日期
     *
     * @param date date 如果是改造的，格式要和获取的格式一致
     * @param rgx 需要获取的格式
     * @return 从日历类中获取年/月/日
     */
    @JvmStatic
    @Deprecated("Use @link {{@link #formatDateTime(Date, String)}}")
    fun getFormatDate(date: Date, rgx: String?): String {
        return formatDateTime(date.time, rgx)
    }

    /**
     * 格式化Date类型的日期
     *
     * @param date date 如果是改造的，格式要和获取的格式一致
     * @param rgx 需要获取的格式
     * @return 从日历类中获取年/月/日
     */
    fun formatDateTime(date: Date, rgx: String?): String {
        return formatDateTime(date.time, rgx)
    }

    /**
     * 将long类型日期格式化为你想要的格式
     *
     * @param dateL 传入以Date获取的long类型值
     * @param rgx 传入你想转化的格式 yyyy-MM-dd HH:mm:ss
     * @return 返回已默认格式转化的时间字符串
     */
    @SuppressLint("SimpleDateFormat")
    fun formatDateTime(dateL: Long, rgx: String?): String {
        val sdf: SimpleDateFormat = SimpleDateFormat(rgx)
        val date: Date = Date(dateL)
        return sdf.format(date)
    }


    //</editor-fold>
    /**
     * 获取日期格式 年/月/日
     *
     * @param mCalendar calendar是带本地时区的
     * @param splitChar 分隔符
     * @return 从日历类中获取年/月/日
     */
    private fun getYMD(mCalendar: Calendar, splitChar: String): String {
        val mYear: Int = mCalendar.get(Calendar.YEAR)
        val mMonth: Int = mCalendar.get(Calendar.MONTH) + 1
        val mDay: Int = mCalendar.get(Calendar.DATE)
        return mYear.toString() + splitChar + mMonth + splitChar + mDay
    }

    /**
     * 获取时间格式 时：分
     *
     * @param mCalendar calendar是带本地时区的
     * @return 从日历类中获取当前时间时：分
     */
    @Deprecated("Use @link{{@link #getHM(Calendar)}}")
    fun getTime(mCalendar: Calendar): String {
        val mHour: Int = mCalendar.get(Calendar.HOUR_OF_DAY)
        val mMinute: Int = mCalendar.get(Calendar.MINUTE)
        return "$mHour:$mMinute"
    }

    /**
     * 获取时间格式 时：分
     *
     * @param mCalendar calendar是带本地时区的
     * @return 从日历类中获取当前时间时：分
     */
    fun getHM(mCalendar: Calendar): String {
        val mHour: Int = mCalendar.get(Calendar.HOUR_OF_DAY)
        val mMinute: Int = mCalendar.get(Calendar.MINUTE)
        return "$mHour:$mMinute"
    }

    /**
     * 对日期进行增加操作
     *
     * @param target 需要进行运算的日期
     * @param hour 小时
     * @return 返回增加后的date
     */
    fun addDateTime(target: Date?, hour: Double): Date? {
        if (null == target || hour < 0) {
            return target
        }

        return Date(target.time + (hour * 60 * 60 * 1000).toLong())
    }

    /**
     * 对日期进行相减操作
     *
     * @param target 需要进行运算的日期
     * @param hour 小时
     * @return 返回减去的date
     */
    fun subDateTime(target: Date?, hour: Double): Date? {
        if (null == target || hour < 0) {
            return target
        }
        return Date(target.time - (hour * 60 * 60 * 1000).toLong())
    }


    /**
     * 转换年月日的分隔符“-”、“/”
     * 如果日期带时分秒,则会返回时分秒的格式
     *
     * @param changeTime 需要转换的日期
     * @return 返回转换分隔符后的日期 “-”转“/”或者“/”转“-”
     */
    fun changeSplitCharYMD(changeTime: String): String {
        try {
            val formatStr: String
            val changeSplitChar: String
            if (changeTime.contains("-")) {
                formatStr = "yyyy-MM-dd"
                changeSplitChar = "/"
            } else if (changeTime.contains("/")) {
                formatStr = "yyyy/MM/dd"
                changeSplitChar = "-"
            } else {
                LogX.e(TAG, "changeSplitCharYMD: 日期分隔符不是“-”或“/”")
                return changeTime
            }
            val format: SimpleDateFormat = SimpleDateFormat(formatStr)
            val date: Date? = format.parse(changeTime)
            return formatDateTime(date!!, "yyyy" + changeSplitChar + "MM" + changeSplitChar + "dd")
        } catch (e: ParseException) {
            return changeTime
        }
    }


    @JvmStatic
    val fileName: String
        /**
         * 用当前时间给图片命名
         *
         * @return 返回yyyyMMdd_HHmmss格式的字符串
         */
        get() {
            val date: Date = Date(System.currentTimeMillis())
            val dateFormat: SimpleDateFormat =
                SimpleDateFormat("yyyyMMdd_HHmmss")
            val random: Random = Random()
            val num: Int = random.nextInt() * 100
            return dateFormat.format(date) + num
        }

    /**
     * 以友好的方式显示时间
     *
     * @param diffTime 传入的时间
     * @return 几分钟前，几小时前的那种朋友圈时间格式
     */
    fun formatFriendlyTime(context: Context, diffTime: Long): String {
        if (diffTime < 0) {
            return "Unknown"
        }
        val diff: Long = diffTime
        var r: Long = 0

        if (diff > year) {
            r = (diff / year)
            //年
            return r.toString() + ResourceUtils.getString(context, R.string.ut_year_ago)
        }
        if (diff > month) {
            r = (diff / month)
            //月
            return r.toString() + ResourceUtils.getString(context, R.string.ut_month_ago)
        }
        if (diff > day) {
            r = (diff / day)
            if (r == 1L) {
                //昨天
                return ResourceUtils.getString(context, R.string.ut_yesterday)
            }
            if (r == 2L) {
                //前天
                return ResourceUtils.getString(context, R.string.ut_before_yesterday)
            }
            //n天前
            return r.toString() + ResourceUtils.getString(context, R.string.ut_day_ago)
        }
        if (diff > hour) {
            r = (diff / hour)
            //n小时前
            return r.toString() + ResourceUtils.getString(context, R.string.ut_hour_ago)
        }
        if (diff > minute) {
            r = (diff / minute)
            //n分钟前
            return r.toString() + ResourceUtils.getString(context, R.string.ut_minute_ago)
        }
        //刚刚
        return ResourceUtils.getString(context, R.string.ut_now)
    }

    /**
     * 返回时间差
     *
     * @param nowtime 开始时间
     * @param endtime 结束时间
     * @return 返回时间差，毫秒数
     */
    fun difference(nowtime: String, endtime: String): Long {
        var split: String = "-"
        if (nowtime.contains("-") && endtime.contains("-")) {
            split = "-"
        } else if (nowtime.contains("/") && endtime.contains("/")) {
            split = "/"
        } else {
            LogX.e(TAG, "### timeDifference:" + "分隔符不正确")
            return 0
        }
        val diff: Long
        //系统时间转化为Date形式
        val dstart: Date? = parseDate(nowtime, split)
        //活动结束时间转化为Date形式
        val dend: Date? = parseDate(endtime, split)
        //算出时间差，用ms表示
        diff = dend!!.time - dstart!!.time
        //返回时间差
        return diff
    }

    /**
     * 将毫秒时长格式化为 00:00:00 这种格式
     *
     * @param time 将毫秒格式化为时间
     * @return 返回格式化好的时间，最大单位为小时
     */
    fun secToTimerTime(time: Long): String {
        var time: Long = time
        val timeStr: String
        val minute: Int
        val second: Int
        val millisecond: Int
        if (time <= 0) {
            return "00:00:000"
        } else {
            millisecond = (time % 1000).toInt()
            time = time / 1000
            minute = (time / 60).toInt()
            second = (time % 60).toInt()
            timeStr = unitFormat(minute) + ":" + unitFormat(second) + ":" + unitmillisecondFormat(
                millisecond
            )
        }
        return timeStr
    }

    /**
     * 格式化成计时器的格式
     * 将毫秒时长格式化为 00'00 这种格式
     * 格式:分'秒"
     *
     * @param time 将毫秒格式化为时间
     * @return 返回格式化好的时间，最大单位为小时
     */
    fun secToShowTime(time: Long): String {
        var time: Long = time
        val timeStr: String
        val minute: Int
        val second: Int
        if (time <= 0) {
            return "00'00"
        } else {
            time = time / 1000
            minute = (time / 60).toInt()
            second = (time % 60).toInt()
            timeStr = unitFormat(minute) + "'" + unitFormat(second)
        }
        return timeStr
    }

    private fun unitFormat(i: Int): String {
        var retStr: String? = null
        if (i >= 0 && i < 10) {
            retStr = "0$i"
        } else {
            retStr = "" + i
        }
        return retStr
    }

    private fun unitmillisecondFormat(i: Int): String {
        var retStr: String?
        if (i >= 0 && i < 10) {
            return "00$i"
        } else if (i >= 10 && i < 100) {
            return "0$i"
        } else {
            return "" + i
        }
    }
}
